<?php
// +----------------------------------------------------------------------
// | A3Mall
// +----------------------------------------------------------------------
// | Copyright (c) 2020 http://www.a3-mall.com All rights reserved.
// +----------------------------------------------------------------------
// | Author: xzncit <158373108@qq.com>
// +----------------------------------------------------------------------

namespace app\common\model\users;

use app\common\model\base\A3Mall;
use think\facade\Db;

class Wallet extends A3Mall{

    protected $name = "wallet";

    protected $type = [
        "user_id"=>"integer",
        "total_amout"=>"float",
        "withdraw_amount"=>"float",
        "non_withdraw_amount"=>"float",
        "frozen_withdraw_amount"=>"float",
        "frozen_non_withdraw_amount"=>"float",
        "ver"=>"integer",
    ];

    /**
     * 类型对应 wallet_details 中的类型
     */
    const WALLET_DETAILS_TYPE_BY_LIST = [
        'JOB_FROZEN' => 'jobFrozen',
        'JOB_UNFROZEN' => 'jobUnfrozen',
        'ISSUE_COST' => 'issueCost',
    ];


    /**
     * 添加用户钱包
     * @param $user_id
     */
    public function insertDefault($user_id) {
        $insertData = [
            "user_id"=>$user_id,
            "total_amout"=>0,
            "withdraw_amount"=>0,
            "non_withdraw_amount"=>0,
            "frozen_withdraw_amount"=>0,
            "frozen_non_withdraw_amount"=>0,
            "ver"=>1,
        ];
        return $this->insert($insertData);

    }


    /**
     * 获取用户余额
     * @param $userId
     */
    public function getBalanceCount($userDetails)
    {
        if(!$userDetails = is_integer($userDetails)?$this->findOne($userDetails):$userDetails) {
            throw new \Exception('用户钱包数据不存在');
        }

        return bcadd($userDetails['withdraw_amount'],$userDetails['non_withdraw_amount'],2) - 0;
    }

    /**
     * 通过用户 ID 获取用户钱包数据
     * @param $userId
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function findOne($userId) {
        $result = $this->where(['user_id'=>$userId])->find();
        return $result;
    }


    /**
     * 任务冻结金额
     * @param $findDetails 资金详情
     * @param $jobId    任务ID
     * @param $amount   冻结金
     */
    public function jobFrozen($findDetails,$jobId,$amount)
    {
        $total = $amount;
        $update = [];
        if($findDetails['non_withdraw_amount'] > 0) {
            $money = $amount > $findDetails['non_withdraw_amount']?$findDetails['non_withdraw_amount']:$amount;
            $update = array_merge($update,[
               'non_withdraw_amount'    => Db::raw('non_withdraw_amount - ' . $money),
               'frozen_non_withdraw_amount' =>  Db::raw('frozen_non_withdraw_amount +' . $money),
            ]);
            $amount = bcsub($amount,$money,2) - 0;
        }

        if($amount > 0) {
            $update = array_merge($update,[
                'withdraw_amount'    =>  Db::raw('withdraw_amount - ' . $amount),
                'frozen_withdraw_amount' => Db::raw('frozen_withdraw_amount +' . $amount),
            ]);
        }
        // 修改资金数据
        $this->updateByIdAndVer($findDetails['user_id'],$findDetails['ver'],$update);

        // 新增冻结记录
        (new WalletDetail())->recordAddFromWallet([
            'amount'    => bcsub(0,$total,2),
            'user_id'   => $findDetails['user_id'],
            'related_id'    => $jobId,
        ],static::WALLET_DETAILS_TYPE_BY_LIST['JOB_FROZEN']);

        // 资金冻结成功，返回
        return true;
    }


    /**
     * 资金解冻
     * @param $findDetails 钱包详情
     * @param $jobId 任务ID
     * @param $amountUnfrozen 解冻金额
     * @param $amountPay 支付金额
     */
    public function jobUnfrozen($findDetails,$jobId,$amountUnfrozen,$amountPay){
        // 获取资绝对值
        $amountUnfrozen = abs($amountUnfrozen);
        $pay = abs($amountPay);
        /**************** 计算解冻金额（可提现、不可提现） *****************/
        $frozenNonWithdrawAmount = bccomp($pay,$findDetails['frozen_non_withdraw_amount'],2) == 1?$findDetails['frozen_non_withdraw_amount']:$pay;
        $frozenWithdrawAmount = bcsub($amountUnfrozen,$frozenNonWithdrawAmount,2);
        if(bccomp($frozenWithdrawAmount,$findDetails['frozen_withdraw_amount'],2) == 1) {
            $frozenNonWithdrawAmount = bcadd($frozenNonWithdrawAmount,bcsub($frozenWithdrawAmount,$findDetails['frozen_withdraw_amount'],2),2);
            $frozenWithdrawAmount = $findDetails['frozen_withdraw_amount'];
            if(bccomp($frozenNonWithdrawAmount,$findDetails['frozen_non_withdraw_amount'],2) == 1) {
                throw new \Exception('冻结金额出错，请联系管理员');
            }
        }

        /************** END 计算解冻金额（可提现、不可提现） ***************/
        $update = [
            'withdraw_amount'    =>  Db::raw('withdraw_amount + ' . $frozenWithdrawAmount),
            'frozen_withdraw_amount' => Db::raw('frozen_withdraw_amount - ' . $frozenWithdrawAmount),
            'non_withdraw_amount'    => Db::raw('non_withdraw_amount + ' . $frozenNonWithdrawAmount),
            'frozen_non_withdraw_amount' =>  Db::raw('frozen_non_withdraw_amount -' . $frozenNonWithdrawAmount),
        ];

        // 修改资金数据
        $this->updateByIdAndVer($findDetails['user_id'],$findDetails['ver'],$update);

        // 新增解冻记录
        (new WalletDetail())->recordAddFromWallet([
            'amount'    => $amountUnfrozen,
            'user_id'   => $findDetails['user_id'],
            'related_id'    => $jobId,
        ],static::WALLET_DETAILS_TYPE_BY_LIST['JOB_UNFROZEN']);

        // 重新获取详情
        if(!$findDetails = $this->findOne($findDetails['user_id'])) {
            throw new \Exception('系统繁忙，请稍后再试');
        }

        // 增加发任务消费记录【存在消费时增加记录】
        if(bccomp($pay,0,2) != 0) {
            (new WalletDetail())->recordAddToWallet($findDetails,bcsub(0,$pay,2),static::WALLET_DETAILS_TYPE_BY_LIST['ISSUE_COST'],[
                'related_id'    => $jobId,
            ]);
        }

        return true;
    }

    /**
     * 通过 钱包详情 更新用户金额（即从 WalletDetails 调用该函数）
     * @param $userId
     * @param $ver
     * @param $withdrawAmount
     * @param $nonWithdrawAmount
     */
    public function updateFromWalletDetaisl($userId,$ver,$withdrawAmount,$nonWithdrawAmount) {
        $totalAmout = bcadd($withdrawAmount,$nonWithdrawAmount,2) - 0;
        $update = [
            'total_amout'   => Db::raw('total_amout' . (bccomp($totalAmout,0,2) == -1?'-':'+') . abs($totalAmout)),
            'withdraw_amount'   => Db::raw('withdraw_amount' . (bccomp($withdrawAmount,0,2) == -1?'-':'+') . abs($withdrawAmount)),
            'non_withdraw_amount'   => Db::raw('non_withdraw_amount' . (bccomp($nonWithdrawAmount,0,2) == -1?'-':'+') . abs($nonWithdrawAmount)),
        ];

        // 修改资金数据
        $this->updateByIdAndVer($userId,$ver,$update);
    }

    /**
     * 通过ID和版本号更新数据
     * @param $userId
     * @param $version
     * @param $updateData
     */
    private function updateByIdAndVer($userId,$version,$updateData)
    {

        $updateData['ver'] = Db::raw('ver+1');
        if(!$this->where([
            'user_id'   => $userId,
            'ver'   => $version,
        ])->update($updateData)) {
            throw new \Exception('数据发生变化，请刷新重试');
        }
        return true;
    }


}
